﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace DevelopTool.Common
{
    /// <summary>
    /// 远程桌面RDP文件生成帮助类
    /// https://blog.csdn.net/weixin_30362233/article/details/96270733
    /// https://www.cnblogs.com/CityOfThousandFires/p/10345436.html
    /// </summary>
    public static class RDPHelper
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct DATA_BLOB
        {
            public int cbData;

            public IntPtr pbData;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct CRYPTPROTECT_PROMPTSTRUCT
        {
            public int cbSize;

            public int dwPromptFlags;

            public IntPtr hwndApp;

            public string szPrompt;
        }
        [DllImport("crypt32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern bool CryptProtectData(ref DATA_BLOB pDataIn, string szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);

        public static string Encrypt(string password)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(password);
            DATA_BLOB dATA_BLOB = default(DATA_BLOB);
            DATA_BLOB dATA_BLOB2 = default(DATA_BLOB);
            DATA_BLOB dATA_BLOB3 = default(DATA_BLOB);
            dATA_BLOB.cbData = bytes.Length;
            dATA_BLOB.pbData = Marshal.AllocHGlobal(bytes.Length);
            Marshal.Copy(bytes, 0, dATA_BLOB.pbData, bytes.Length);
            dATA_BLOB3.cbData = 0;
            dATA_BLOB3.pbData = IntPtr.Zero;
            dATA_BLOB2.cbData = 0;
            dATA_BLOB2.pbData = IntPtr.Zero;
            CRYPTPROTECT_PROMPTSTRUCT cRYPTPROTECT_PROMPTSTRUCT = new CRYPTPROTECT_PROMPTSTRUCT
            {
                cbSize = Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT)),
                dwPromptFlags = 0,
                hwndApp = IntPtr.Zero,
                szPrompt = null
            };
            if (CryptProtectData(ref dATA_BLOB, "psw", ref dATA_BLOB3, IntPtr.Zero, ref cRYPTPROTECT_PROMPTSTRUCT, 1, ref dATA_BLOB2))
            {
                if (IntPtr.Zero != dATA_BLOB.pbData)
                {
                    Marshal.FreeHGlobal(dATA_BLOB.pbData);
                }
                if (IntPtr.Zero != dATA_BLOB3.pbData)
                {
                    Marshal.FreeHGlobal(dATA_BLOB3.pbData);
                }
                byte[] array = new byte[dATA_BLOB2.cbData];
                Marshal.Copy(dATA_BLOB2.pbData, array, 0, dATA_BLOB2.cbData);
                return BitConverter.ToString(array).Replace("-", string.Empty);
            }
            return string.Empty;

        }
  

        /// <summary>
        /// 文件内容详细说明
        /// https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/rdp-files
        /// https://learn.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/rdp-files
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="address"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public static void CreateProfile(string filename, string address, string username, string password)
        {
            if (File.Exists(filename))
            {
                File.Delete(filename);
            }
            using (StreamWriter streamWriter = new StreamWriter(filename, true))
            {
                streamWriter.WriteLine("allow desktop composition:i:0");
                streamWriter.WriteLine("enablecredsspsupport:i:1");//确定客户端是否将使用凭据安全支持提供程序 （CredSSP） 进行身份验证（如果可用）。
                streamWriter.WriteLine("enablerdsaadauth:i:1");//确定客户端是否将使用 Azure AD 向远程电脑进行身份验证（如果可用）。
                streamWriter.WriteLine("disableconnectionsharing:i:0");//确定客户端是重新连接到任何现有的已断开连接的会话，还是在启动新连接时启动新连接。
                streamWriter.WriteLine("redirected video capture encoding quality:i:1");//控制编码视频的质量。
                streamWriter.WriteLine("allow font smoothing:i:0");
                streamWriter.WriteLine("alternate shell:s:");
                streamWriter.WriteLine("audiocapturemode:i:1");
                streamWriter.WriteLine("audiomode:i:0");//	音频输出位置：确定本地还是远程计算机播放音频。 - 0：在本地计算机上播放声音（在此计算机上播放）-1：在远程计算机上播放声音（在远程计算机上播放）-2：不播放声音（不播放）
                streamWriter.WriteLine("authentication level:i:2");
                streamWriter.WriteLine("autoreconnection enabled:i:1");//确定如果连接断开（例如，当网络连接中断时），客户端是否会自动尝试重新连接到远程计算机。
                streamWriter.WriteLine("bandwidthautodetect:i:1");//确定是否使用自动网络带宽检测。需要将带宽自动检测设置为 1。
                streamWriter.WriteLine("bitmapcachepersistenable:i:1");
                streamWriter.WriteLine("compression:i:1");//确定在通过 RDP 将大容量压缩传输到本地计算机时是否启用大容量压缩。
                streamWriter.WriteLine("connection type:i:7");
                streamWriter.WriteLine("desktopheight:i:900");
                streamWriter.WriteLine("desktopwidth:i:1440");
                streamWriter.WriteLine("disable cursor setting:i:0");
                streamWriter.WriteLine("disable full window drag:i:1");
                streamWriter.WriteLine("disable menu anims:i:1");
                streamWriter.WriteLine("disable themes:i:0");
                streamWriter.WriteLine("disable wallpaper:i:0");
                streamWriter.WriteLine("displayconnectionbar:i:1");
                streamWriter.WriteLine("drivestoredirect:s:");
                streamWriter.WriteLine("enableworkspacereconnect:i:0");
                streamWriter.WriteLine("full address:s:" + address);//此设置指定要连接到的远程计算机的名称或IP地址。
                streamWriter.WriteLine("gatewaybrokeringtype:i:0");
                streamWriter.WriteLine("gatewaycredentialssource:i:4");
                streamWriter.WriteLine("gatewayhostname:s:");//指定RD网关主机名。
                streamWriter.WriteLine("gatewayprofileusagemethod:i:0");
                streamWriter.WriteLine("gatewayusagemethod:i:4");
                streamWriter.WriteLine("kdcproxyname:s:");
                streamWriter.WriteLine("keyboardhook:i:2");
                streamWriter.WriteLine("negotiate security layer:i:1");
                streamWriter.WriteLine("networkautodetect:i:1");//确定是否启用自动网络类型检测
                streamWriter.WriteLine("prompt for credentials:i:0");
                streamWriter.WriteLine("promptcredentialonce:i:0");
                streamWriter.WriteLine("rdgiskdcproxy:i:0");
                streamWriter.WriteLine("redirectclipboard:i:1");//剪贴板:1打开,0关闭
                streamWriter.WriteLine("redirectcomports:i:0");
                streamWriter.WriteLine("redirectposdevices:i:0");
                streamWriter.WriteLine("redirectprinters:i:1"); //打印机:1打开,0关闭
                streamWriter.WriteLine("redirectsmartcards:i:1");
                streamWriter.WriteLine("remoteapplicationmode:i:0");
                streamWriter.WriteLine("screen mode id:i:2");
                streamWriter.WriteLine("session bpp:i:32");
                streamWriter.WriteLine("shell working directory:s:");
                streamWriter.WriteLine("use multimon:i:0");
                streamWriter.WriteLine("use redirection server name:i:0");
                streamWriter.WriteLine("videoplaybackmode:i:1");//确定连接是否将使用 RDP 高效的多媒体流进行视频播放。
                streamWriter.WriteLine("winposstr:s:0,3,0,0,800,600");
                if (!string.IsNullOrEmpty(username))
                {
                    streamWriter.WriteLine("username:s:" + username);//指定将用于登录到远程计算机的用户帐户的名称。
                }
                if (!string.IsNullOrEmpty(password))
                {
                    streamWriter.WriteLine("password 51:b:" + Encrypt(password));
                }
            }
        }



        //调用方式
        //string path = @"C:\rr\aa.rdp";
        //RDPHelper.CreateProfile(path, "192.186.2.1", "administrator", "abc123");
        //System.Diagnostics.Process.Start("mstsc.exe", path);

    }
}